home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
ada
/
gwuada_9.zip
/
GEN.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-07-27
|
25KB
|
1,049 lines
/*
* Copyright (C) 1985-1992 New York University
*
* This file is part of the Ada/Ed-C system. See the Ada/Ed README file for
* warranty (none) and distribution info and also the GNU General Public
* License for more details.
*/
#define GEN
#include "hdr.h"
#include "vars.h"
#include "gvars.h"
#include "ops.h"
#include "segment.h"
#include "slot.h"
#include "attr.h"
#include "genop.h"
#include "opdescp.h"
#include "segmentp.h"
#include "gpredefp.h"
#include "peepp.h"
#include "setp.h"
#include "miscp.h"
#include "gmiscp.h"
#include "smiscp.h"
#include "genp.h"
static void gen_kfc(int, int, long, char *);
static void gen_krc(int, int, float, char *);
static void gen_r(int, Explicit_ref);
static void gop_int(int, int, int, int, char *);
static void gop_fix(int, int, int, long, char *);
static void gop_flt(int, int, int, float, char *);
static void gop_ref(int, int, int, Explicit_ref, char *);
static void gop_sym(int, int, int, Symbol, char *);
#ifdef DEBUG
static void undone_op(int, char *);
#endif
static char *g_kind(int);
static int adjust(int);
static int int_adjust(int);
static int fix_adjust(int);
static int float_adjust(int);
static void pretty_addr(int);
static void asm_exception(Symbol);
static void asm_byte(int);
static void asm_int(int);
static void asm_fix(long);
static void asm_flt(float);
static void asm_seg(int);
static void asm_off(int);
static void G_int(int);
static void G_fix(long);
static void G_flt(float);
#ifdef DEBUG
static void zpop(Op);
#endif
static void gref_sort(Tuple, int);
static int gref_compare_name(Gref *, Gref *);
static int gref_compare_address(Gref *, Gref *);
static char *gs_end();
extern Segment CODE_SEGMENT, DATA_SEGMENT, DATA_SEGMENT_MAIN;
/*
2-jun
note that calls to gen(I_DISCARD_ADDR, n, ..) always have 1 as the
second argument. This is kept in 'kind' field. The third argument
is not always present, in which case (Symbol)0 should be written.
5-jul ds
Translated the two calls to gen(I_CASE_TABLE ...) in stat.c as
gen_ks.
---
Translate the calls for gen(I_ATTRIBUTE, ...) to the form
gen_kv(...) using (Const) 0 for third arg in cases where SETL
has only two args.
15-jul ds
Note following from mail note from Rosen:
The integer value is the numb of addresses to discard. It is normally one,
but the peep-hole optimizer may merge severall consecutives discard_addr
into one.
Note that the symbol name is given in the COMMENT field (and may thus be
omitted). If present, it is used by the peep-hole optimizer to trap things
like:
discard_addr 1 --symbol
push_addr symbol
*/
static char G_s[256]; /* for trace output of instructions */
/* macro to position at end of G_s */
char *gs_end();
#define G_END gs_end()
/* create dummy entry for p (np is string with name of p)
* and call chaos if p is called
* Current operand types:
* gen_i integer
* gen_k kind (from kind_of, offset added to opcode to get
* final opcode) this field is also used for integer
* for i_discard_address (always 1) and for attribute
* code (<= 50) for I_ATTRIBUTE.
* gen_kc
* gen_ki
* gen_kic
* gen_ks kind and symbol
* gen_ksc
* gen_kv kind and value (Const), used mainly for push_immediate
* instructions. The v argument must be Const.
* gen_kvc
* gen_r explicit reference (two args: segment and offset)
* in this case segment and offset always zero!!
* gen_rc
* gen_s symbol
* gen_sc
*/
struct Op_s op_next;
/* set values in global variable op_next, needed copying done by assemble */
#define gop_new(opc, k, ka, c) op_next.op_code = opc; op_next.op_kind = k;\
op_next.op_type = ka; op_next.op_com = c;
#ifdef DEBUG
#define undone(p, np) p(op) int op; { undone_op(op, np);}
#endif
void gen(int opc) /*;gen*/
{
gop_int(opc, 0, 0, 0, (char *)0);
}
void gen_c(int opc, char *c) /*;gen_c*/
{
gop_int(opc, 0, 0, 0, c);
}
void gen_i(int opc, int i) /*;gen_i*/
{
gen_ic(opc, i, (char *)0);
}
void gen_ic(int opc, int i, char *c) /*;gen_ic*/
{
gop_int(opc, 0, OP_INT, i, c);
}
void gen_k(int opc, int k) /*;gen_k*/
{
gen_kc(opc, k, (char *)0);
}
void gen_kc(int opc, int k, char *c) /*;gen_k*/
{
gop_int(opc, k, OP_INT, 0, c);
}
void gen_ki(int opc, int k, int n) /*;gen_ki*/
{
gen_kic(opc, k, n, (char *)0);
}
void gen_kic(int opc, int k, int n, char *c) /*;gen_kic*/
{
gop_int(opc, k, OP_INT, n, c);
}
static void gen_kfc(int opc, int k, long n, char *c) /*;gen_kfc*/
{
gop_fix(opc, k, OP_FIX, n, c);
}
static void gen_krc(int opc, int k, float n, char *c) /*;gen_krc*/
{
gop_flt(opc, k, OP_FLT, n, c);
}
void gen_ks(int opc, int k, Symbol sym) /*;gen_ks*/
{
gen_ksc(opc, k, sym, (char *)0);
}
void gen_ksc(int opc, int k, Symbol sym, char *c) /*;gen_ksc*/
{
/* Note that I_DISCARD_ADDR has symbol supplied only for use
* by peephole optimizer. Since this is disable for now,
* ignore the symbol arg for this operation.
*/
if (opc == I_DISCARD_ADDR)
gen_kic(opc, k, k, c);
else
gop_sym(opc, k, OP_SYM, sym, (char *)c);
}
void gen_kv(int opc, int k, Const ref) /*;gen_kv*/
{
gen_kvc(opc, k, ref, (char *)0);
}
void gen_kvc(int opc, int k, Const ref, char *c) /*;gen_kvc*/
{
/* Need to get value from Const and see if length compatible with
* k argument
* Suppress check for now, just handle int's and longs, and
* also assume longs same size as ints
* TBSL: need to add checks, handle other const types, handle
* longs differently for PC ds 7-15-85
*/
int ctype;
ctype = ref->const_kind;
if (ctype == CONST_INT) {
gen_kic(opc, k, INTV(ref), c);
}
else if (ctype == CONST_FIXED) {
gen_kfc(opc, k, FIXEDV(ref), c);
}
else if (ctype == CONST_REAL) {
/* Note that treating ada reals as C reals here */
gen_krc(opc, k, REALV(ref), c);
}
else {
chaos("gop const undefined case");
}
}
static void gen_r(int opc, Explicit_ref ref) /*;gen_r*/
{
gen_rc(opc, ref, (char *)0);
}
void gen_rc(int opc, Explicit_ref ref, char *c) /*;gen_rc*/
{
gop_ref(opc, 0, OP_REF, ref, c);
}
void gen_s(int opc, Symbol s) /*;gen_s*/
{
gen_sc(opc, s, (char *)0);
}
void gen_sc(int opc, Symbol s, char *c) /*;gen_sc*/
{
gop_sym(opc, 0, OP_SYM, s, c);
}
static void gop_int(int opc, int k, int ka, int arg, char *c) /*;gop_int*/
{
gop_new(opc, k, ka, c);
op_next.op_arg.arg_int = arg;
peep_hole(&op_next);
}
static void gop_fix(int opc, int k, int ka, long arg, char *c) /*;gop_fix*/
{
gop_new(opc, k, ka, c);
op_next.op_arg.arg_fix = arg;
peep_hole(&op_next);
}
static void gop_flt(int opc, int k, int ka, float arg, char *c) /*;gop_flt*/
{
gop_new(opc, k, ka, c);
op_next.op_arg.arg_flt = arg;
peep_hole(&op_next);
}
static void gop_ref(int opc, int k, int ka, Explicit_ref arg, char *c)
/*;gop_ref*/
{
gop_new(opc, k, ka, c);
op_next.op_arg.arg_ref = arg;
peep_hole(&op_next);
}
static void gop_sym(int opc, int k, int ka, Symbol arg, char *c) /*;gop_sym*/
{
gop_new(opc, k, ka, c);
op_next.op_arg.arg_sym = arg;
peep_hole(&op_next);
}
#ifdef DEBUG
static void undone_op(int op, char *np) /*;undone_op*/
{
/* print name of generation procedure and name of operation */
extern char *opdesc_name;
opdesc(op);
printf("op %s %s\n", np, opdesc_name);
}
#endif
void assemble(Op op) /*;assemble*/
{
int code;
Symbol lab_name, new_lab, obj_name;
extern char *opdesc_name;
int data_mode, addr_mode, addressing_mode;
int adj, b, off, type, loc, opkind, value;
extern int opdesc_a_mode, opdesc_d_mode;
Explicit_ref eref;
Tuple labtup, eqtup, newtup, patch_tup;
Fortup ft1, ft2;
int code_start;
#ifdef MACHINE_CODE
if (list_code) { /* initialize G_s for trace output */
G_s[0] = '\0';
obj_name = (Symbol) 0; /* set nonzero if symbol for trace output*/
}
#endif
/* label handling */
code_start = PC();
code = op->op_code;
opkind = op->op_kind;
type = op->op_type;
if (code == I_LABEL) {
lab_name = op->op_arg.arg_sym;
#ifdef MACHINE_CODE
if (list_code) {
/*TO_GEN(pretty_addr + ' '*12 + lab_name + ':');*/
pretty_addr(code_start);
if (ORIG_NAME(lab_name) != (char *)0) {
sprintf(G_END, " s%du%d %s:",
S_SEQ(lab_name), S_UNIT(la